<template>
  <div class="flex relative w-full items-center" :class="prefixCls">
    <span
      class="w-35 h-full flex relative v-tags-view__tool--first items-center justify-center cursor-pointer"
      @click="move(-200)"
    >
      <el-icon><DArrowLeft /></el-icon
    ></span>
    <div class="overflow-hidden flex-1 h-full">
      <ElScrollbar ref="scrollbarRef" class="h-full" @scroll="scroll">
        <div class="flex h-full">
          <ContextMenu
            :ref="itemRefs.set"
            :schema="[
              {
                icon: 'vi-ant-design:sync-outlined',
                label: '重新加载',
                disabled: selectedTag?.fullPath !== item.fullPath,
                command: () => {
                  refreshSelectedTag(item);
                },
              },
              {
                icon: 'vi-ant-design:close-outlined',
                label: '关闭标签页',
                disabled: !!visitedViews?.length && selectedTag?.meta.affix,
                command: () => {
                  closeSelectedTag(item);
                },
              },
              {
                divided: true,
                icon: 'vi-ant-design:vertical-right-outlined',
                label: '关闭左侧标签页',
                disabled:
                  !!visitedViews?.length &&
                  (item.fullPath === visitedViews[0].fullPath ||
                    selectedTag?.fullPath !== item.fullPath),
                command: () => {
                  closeLeftTags();
                },
              },
              {
                icon: 'vi-ant-design:vertical-left-outlined',
                label: '关闭右侧标签页',
                disabled:
                  !!visitedViews?.length &&
                  (item.fullPath === visitedViews[visitedViews.length - 1].fullPath ||
                    selectedTag?.fullPath !== item.fullPath),
                command: () => {
                  closeRightTags();
                },
              },
              {
                divided: true,
                icon: 'vi-ant-design:tag-outlined',
                label: ' 关闭其它标签页',
                disabled: selectedTag?.fullPath !== item.fullPath,
                command: () => {
                  closeOthersTags();
                },
              },
              {
                icon: 'vi-ant-design:line-outlined',
                label: '关闭全部标签页',
                command: () => {
                  closeAllTags();
                },
              },
            ]"
            v-for="item in visitedViews"
            :key="item.fullPath"
            :tag-item="item"
            :class="[
              `${prefixCls}__item`,
              item?.meta?.affix ? `${prefixCls}__item--affix` : '',
              {
                'is-active': isActive(item),
              },
            ]"
            @visible-change="visibleChange"
          >
            <div>
              <router-link
                :ref="tagLinksRefs.set"
                :to="{ ...item }"
                custom
                v-slot="{ navigate }"
              >
                <div
                  class="h-full flex justify-center items-center whitespace-nowrap pl-15px"
                  @click="navigate"
                >
                  {{ item?.meta?.title }}
                  <IconPark
                    v-if="!item?.meta.affix"
                    class="tags-view__item--close"
                    color="#333"
                    type="close"
                    :size="12"
                    @click.prevent.stop="closeSelectedTag(item)"
                  />
                </div>
              </router-link>
            </div>
          </ContextMenu>
        </div>
      </ElScrollbar>
    </div>
    <span
      class="w-35 h-full relative flex v-tags-view__tool items-center justify-center cursor-pointer"
      @click="move(200)"
    >
      <el-icon><DArrowRight /></el-icon>
    </span>
    <span
      class="w-35 h-full relative v-tags-view__tool flex items-center justify-center cursor-pointer"
      @click="refreshSelectedTag(selectedTag)"
    >
      <IconPark type="redo" :size="16" />
    </span>
    <span
      class="w-35 h-full relative v-tags-view__tool flex items-center justify-center cursor-pointer"
    >
      <ContextMenu
        trigger="click"
        :schema="[
          {
            icon: 'vi-ant-design:sync-outlined',
            label: '重新加载',
            command: () => {
              refreshSelectedTag(selectedTag);
            },
          },
          {
            icon: 'vi-ant-design:close-outlined',
            label: '关闭标签页',
            disabled: !!visitedViews?.length && selectedTag?.meta.affix,
            command: () => {
              closeSelectedTag(selectedTag);
            },
          },
          {
            divided: true,
            icon: 'vi-ant-design:vertical-right-outlined',
            label: '关闭左侧标签页',
            disabled:
              !!visitedViews?.length &&
              selectedTag?.fullPath === visitedViews[0].fullPath,
            command: () => {
              closeLeftTags();
            },
          },
          {
            icon: 'vi-ant-design:vertical-left-outlined',
            label: '关闭右侧标签页',
            disabled:
              !!visitedViews?.length &&
              selectedTag?.fullPath === visitedViews[visitedViews.length - 1].fullPath,
            command: () => {
              closeRightTags();
            },
          },
          {
            divided: true,
            icon: 'vi-ant-design:tag-outlined',
            label: '关闭其它标签页',
            command: () => {
              closeOthersTags();
            },
          },
          {
            icon: 'vi-ant-design:line-outlined',
            label: '关闭全部标签页',
            command: () => {
              closeAllTags();
            },
          },
        ]"
      >
        <IconPark type="config" :size="16"
      /></ContextMenu>
    </span>
  </div>
</template>

<script setup>
import IconPark from "@/components/library/IconPark.vue";
import { filterAffixTags } from "./helper";
import { useTemplateRefsList } from "@vueuse/core";
import { cloneDeep } from "lodash-es";
import { onMounted, computed, watch, unref, nextTick } from "vue";
import ContextMenu from "./ContextMenu.vue";
import { useTagsViewStore } from "@/store/tagsView";
import { useScrollTo } from "@/hooks/event/useScrollTo";
import { useTagsView } from "@/hooks/web/useTagsView";
import { usePermissionStore } from "@/store/permission";
import { useRouter } from "vue-router";
const prefixCls = "v-tags-view";
import { storeToRefs } from "pinia";
import { ref } from "vue";
const tagsViewStore = useTagsViewStore();
const selectedTag = computed(() => tagsViewStore.getSelectedTag);
const visitedViews = computed(() => tagsViewStore.getVisitedViews);
const { currentRoute, push } = useRouter();
import { useFoldMenuStore } from "@/store/foldMenu";
const {
  closeAll,
  closeLeft,
  closeRight,
  closeOther,
  closeCurrent,
  refreshPage,
} = useTagsView();

const foldMenu = useFoldMenuStore();
const { menus } = storeToRefs(foldMenu);
const permissionStore = usePermissionStore();
// 保存滚动位置
const scrollLeftNumber = ref(0);
// elscroll 实例
const scrollbarRef = ref();
// 所有右键菜单组件的元素
const itemRefs = useTemplateRefsList();
const tagLinksRefs = useTemplateRefsList();

const setSelectTag = tagsViewStore.setSelectedTag;
defineOptions({
  name: "TagsView",
});
// 是否是当前tag
const isActive = (route) => route.path === unref(currentRoute).path;
const scroll = ({ scrollLeft }) => {
  scrollLeftNumber.value = scrollLeft;
};
/**
 * 右键菜单状态改变的时候
 * @param {boolean} visible
 * @param {RouteLocationNormalizedLoaded} tagItem
 */
const visibleChange = (visible, tagItem) => {
  if (visible) {
    for (const v of unref(itemRefs)) {
      const elDropdownMenuRef = v.elDropdownMenuRef;
      if (tagItem.fullPath !== v.tagItem.fullPath) {
        elDropdownMenuRef?.handleClose();
        setSelectTag(tagItem);
      }
    }
  }
};
const affixTagArr = ref([]);
// 移动到某个位置
const move = (to) => {
  const wrap$ = unref(scrollbarRef)?.wrapRef;
  const { start } = useScrollTo({
    el: wrap$,
    position: "scrollLeft",
    to: unref(scrollLeftNumber) + to,
    duration: 500,
  });
  start();
};
const initTags = () => {
  affixTagArr.value = filterAffixTags(unref(menus));
  for (const tag of unref(affixTagArr)) {
    if (tag.meta.title) {
      tagsViewStore.addVisitedView(cloneDeep(tag));
    }
  }
};
const addTags = () => {
  const { name } = unref(currentRoute);
  if (name) {
    setSelectTag(unref(currentRoute));
    tagsViewStore.addView(unref(currentRoute));
  }
};
//滚动到选中的tag
const moveToCurrentTag = async () => {
  await nextTick();
  for (const v of unref(visitedViews)) {
    if (v.fullPath === unref(currentRoute).path) {
      moveToTarget(v);
      if (v.fullPath !== unref(currentRoute).fullPath) {
        tagsViewStore?.updateVisitedView(unref(currentRoute));
      }
      break;
    }
  }
};
const moveToTarget = (currentTag) => {
  const wrap$ = scrollbarRef.value?.wrapRef;
  let firstTag = null;
  let lastTag = null;
  const tagList = unref(tagLinksRefs);
  if (tagList.length > 0) {
    firstTag = tagList[0];
    lastTag = tagList[tagList.length - 1];
  }
  if (firstTag?.to.fullPath === currentTag.fullPath) {
    // 直接滚动到0的位置
    const { start } = useScrollTo({
      el: wrap$,
      position: "scrollLeft",
      to: 0,
      duration: 500,
    });
    start();
  } else if (lastTag?.to.fullPath === currentTag.fullPath) {
    // 滚动到最后的位置
    const { start } = useScrollTo({
      el: wrap$,
      position: "scrollLeft",
      to: wrap$.scrollWidth - wrap$.offsetWidth,
      duration: 500,
    });
    start();
  } else {
    // find preTag and nextTag
    const currentIndex = tagList.findIndex(
      (item) => item?.to.fullPath === currentTag.fullPath
    );
    const tgsRefs = document.getElementsByClassName(`${prefixCls}__item`);

    const prevTag = tgsRefs[currentIndex - 1];
    const nextTag = tgsRefs[currentIndex + 1];
    // console.log(" nextTag.offsetLeft", nextTag.offsetLeft);
    // the tag's offsetLeft after of nextTag
    const afterNextTagOffsetLeft = nextTag?.offsetLeft + nextTag.offsetWidth + 4;

    // the tag's offsetLeft before of prevTag
    const beforePrevTagOffsetLeft = prevTag?.offsetLeft - 4;

    if (afterNextTagOffsetLeft > unref(scrollLeftNumber) + wrap$.offsetWidth) {
      const { start } = useScrollTo({
        el: wrap$,
        position: "scrollLeft",
        to: afterNextTagOffsetLeft - wrap$?.offsetWidth,
        duration: 500,
      });
      start();
    } else if (beforePrevTagOffsetLeft < unref(scrollLeftNumber)) {
      const { start } = useScrollTo({
        el: wrap$,
        position: "scrollLeft",
        to: beforePrevTagOffsetLeft,
        duration: 500,
      });
      start();
    }
  }
};

// 重新加载
const refreshSelectedTag = async (view) => {
  refreshPage(view);
};
// 去最后一个
const toLastView = () => {
  const visitedViews = tagsViewStore.getVisitedViews;
  const latestView = visitedViews.slice(-1)[0];
  if (latestView) {
    push(latestView);
  } else {
    if (
      unref(currentRoute).path === permissionStore.getAddRouters[0].path ||
      unref(currentRoute).path === permissionStore.getAddRouters[0].redirect
    ) {
      addTags();
      return;
    }
    // You can set another route
    push(permissionStore.getAddRouters[0].path);
  }
};
const closeSelectedTag = (view) => {
  closeCurrent(view, () => {
    if (isActive(view)) {
      toLastView();
    }
  });
};
const closeLeftTags = () => {
  closeLeft();
};
const closeRightTags = () => {
  closeRight();
};
const closeOthersTags = () => {
  closeOther();
};
const closeAllTags = () => {
  closeAll(() => {
    toLastView();
  });
};
onMounted(() => {
  initTags();
  addTags();
});
watch(
  () => currentRoute.value,
  () => {
    addTags();
    moveToCurrentTag();
  }
);
</script>

<style lang="scss" scoped>
//.v-tags-view__tool--first {
//  &::before {
//    position: absolute;
//    top: 1px;
//    left: 0;
//    width: 100%;
//    height: calc(100% - 1px);
//    border-right: 1px solid var(--el-border-color);
//    content: "";
//  }
//}
//.v-tags-view__tool {
//  &::before {
//    position: absolute;
//    top: 1px;
//    left: 0;
//    width: 100%;
//    height: calc(100% - 1px);
//    border-left: 1px solid var(--el-border-color);
//    content: "";
//  }
//}
.v-tags-view {
  position: relative;
  background-color: #fff;
  height: 40px;
  &::after {
    content: "";
    position: absolute;
    bottom: 0;
    left: 0;
    width: 100%;
    height: 1px;
    background-color: #dcdfe6;
    z-index: 3;
  }
  :deep(.el-scrollbar__view) {
    height: 100%;
  }
  &__tool {
    position: relative;

    &::before {
      position: absolute;
      top: 1px;
      left: 0;
      width: 100%;
      height: calc(100% - 1px);
      border-left: 1px solid var(--el-border-color);
      content: "";
    }

    &--first {
      &::before {
        position: absolute;
        top: 1px;
        left: 0;
        width: 100%;
        height: calc(100% - 1px);
        border-right: 1px solid var(--el-border-color);
        border-left: none;
        content: "";
      }
    }
  }

  &__item {
    position: relative;
    top: 2px;
    height: calc(100% - 6px);
    padding-right: 25px;
    margin-left: 4px;
    font-size: 12px;
    cursor: pointer;
    border: 1px solid #d9d9d9;
    border-radius: 2px;

    &--close {
      position: absolute;
      top: 50%;
      right: 5px;
      display: none;
      transform: translate(0, -50%);
    }
    &:not(v-tags-view__item--affix):hover {
      .v-tags-view__item--close {
        display: block;
      }
    }
    &:not(.v-tags-view_item--affix):hover {
      .v-tags-view__item--close {
        display: block;
      }
    }
  }

  &__item:not(.is-active) {
    &:hover {
      color: var(--el-color-primary);
    }
  }

  &__item.is-active {
    color: var(--el-color-white);
    background-color: var(--el-color-primary);
    border: 1px solid var(--el-color-primary);
    .v-tags-view__item--close {
      :deep(svg) {
        color: var(--el-color-white) !important;
      }
    }
  }
}
</style>
